<?php

declare(strict_types=1);
/**
 * This file is part of habo_new_media.
 *
 * @link     https://www.berlen.cn/
 * @contact  tech@berlen.cn
 * @license  http://gitlab.rehou.cn/habo/habo_new_media/-/blob/master/README.md
 */
namespace app\service\analysis\data\account;

use app\model\AccountProductSalesmanModel;
use app\model\mongo\MongoClientAccountTypeDayStatModel;
use app\model\mongo\MongoProductAccountTypeDayStatModel;
use app\model\mongo\MongoStatModel;
use app\service\analysis\report\ReportAccountService;
use app\service\BaseService;
use app\service\client\ProductService;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\Model;

/**
 * 账户-按客户+媒体+产品+日+账户类型汇总.
 */
final class ProductAccountTypeStatService extends BaseService
{
    /**
     * @var array 销售列表
     */
    private static array $_salesList = [];

    /**
     * @var int 企业id
     */
    private int $companyId;

    /**
     * @var int 客户id
     */
    private int $clientId;

    /**
     * @var int 媒体id
     */
    private int $mediaId;

    /**
     * @var int 账户类型
     */
    private int $accountType;

    /**
     * @var int 产品类型
     */
    private int $productId;

    /**
     * @var int 汇总日期
     */
    private int $statDate;

    /**
     * @var null|ReportAccountService 账户服务
     */
    private ?ReportAccountService $service;

    public function __construct()
    {
    }

    /**
     * 执行任务
     *
     * @param array $arr 信息
     * @return bool
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function runTask(array $arr = []): bool
    {
        $this->companyId = intval($arr[0] ?? 0);
        $this->clientId = intval($arr[1] ?? 0);
        $this->mediaId = intval($arr[2] ?? 0);
        $this->accountType = intval($arr[3] ?? 0);
        $this->statDate = intval($arr[4] ?? 0);
        $this->productId = intval($arr[5] ?? 0);

        if (! $this->checkProperty()) {
            return false;
        }
        $this->service = new ReportAccountService($this->mediaId);
        if (! $this->service->isService()) {
            return false;
        }
        return $this->setStat();
    }

    /**
     * 属性检查.
     */
    private function checkProperty(): bool
    {
        if (empty($this->companyId)) {
            return self::setError('未知企业');
        }
        if (empty($this->clientId)) {
            return self::setError('未知客户');
        }
        if (empty($this->mediaId)) {
            return self::setError('未知媒体');
        }
        if (empty($this->accountType)) {
            return self::setError('未知账户类型');
        }
        if (empty($this->statDate)) {
            return self::setError('未知汇总日期');
        }
        if (empty($this->productId)) {
            return self::setError('未知产品');
        }
        return true;
    }

    /**
     * 设置汇总数据.
     *
     * @return bool
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    private function setStat(): bool
    {
        $model = $this->getStatModel();
        if (! $model->getKey()) {
            $data = [
                'company_id' => $this->companyId,
                'client_id' => $this->clientId,
                'media_id' => $this->mediaId,
                'account_type' => $this->accountType,
                'stat_date' => $this->statDate,
                'product_id' => $this->productId,
                'xs_id' => $this->getSalesField('xs_id'),
                'zl_id' => $this->getSalesField('zl_id'),
                'is_change' => MongoStatModel::IS_CHANGE_YES,
            ];
        } else {
            $data = [
                'is_change' => MongoStatModel::IS_CHANGE_YES,
            ];
        }
        $data = $this->getStatField($data);
        $model->setAttrs($data);
        if (! $model->save()) {
            return self::setError('保存汇总数据失败');
        }
        return true;
    }

    /**
     * 获取汇总模型.
     *
     * @return array|mixed|Model|MongoClientAccountTypeDayStatModel
     */
    private function getStatModel()
    {
        return (new MongoProductAccountTypeDayStatModel())
            ->where([
                'company_id' => $this->companyId,
                'client_id' => $this->clientId,
                'media_id' => $this->mediaId,
                'account_type' => $this->accountType,
                'stat_date' => $this->statDate,
                'product_id' => $this->productId,
            ])
            ->findOrEmpty();
    }

    /**
     * 获取汇总字段值
     * @param array $data 数据值
     */
    private function getStatField(array $data = []): array
    {
        $map = [
            'company_id' => $this->companyId,
            'client_id' => $this->clientId,
            'account_type' => $this->accountType,
            'stat_date' => $this->statDate,
            'product_id' => $this->productId,
        ];
        $stat = $this->service->getDayStat($map);
        $data['cost'] = $stat['cost'] ?? 0;
        $data['balance'] = $stat['balance'] ?? 0;
        $data['cash_cost'] = $stat['cash_cost'] ?? 0;
        $data['reward_cost'] = $stat['reward_cost'] ?? 0;
        return $data;
    }

    /**
     * 初始化账户相关信息.
     *
     * @param string $field 字段名
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    private function getSalesField(string $field = ''): int
    {
        $key = implode('_', [$this->productId, $this->mediaId, $this->accountType]);
        if (! isset(self::$_salesList[$key])) {
            self::$_salesList[$key] = ProductService::getProductSalesman($this->productId, $this->mediaId, $this->accountType);
        }
        $model = self::$_salesList[$key] ?? null;
        if (! $model instanceof AccountProductSalesmanModel || ! $model->getKey()) {
            return 0;
        }

        if (! $field) {
            return 0;
        }
        return intval($model->getAttr($field));
    }
}
